package com.util;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.config.Constant;
import com.config.URLConstant;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.request.OapiGetJsapiTicketRequest;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.response.OapiGetJsapiTicketResponse;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.oapi.lib.aes.DingTalkJsApiSingnature;

/**
 * AccessToken和jsticket的获取封装
 */
public class AuthHelper {
    private static final Logger bizLogger = LoggerFactory.getLogger(AuthHelper.class);

    /**
     ** 调整到1小时50分钟
     */
    public static final long cacheTime = 1000 * 60 * 55 * 2;

    /**
     ** 在此方法中，为了避免频繁获取access_token， 在距离上一次获取access_token时间在两个小时之内的情况， 将直接从持久化存储中读取access_token
     */
    public static String getAccessToken() {
        String secret = Constant.APPKEY + Constant.APPSECRET;
        long curTime = System.currentTimeMillis();
        JSONObject accessTokenValue = (JSONObject) FileUtils.getValue("accesstoken", secret);
        String accToken = "";
        JSONObject jsontemp = new JSONObject();
        if (accessTokenValue == null || curTime - accessTokenValue.getLong("begin_time") >= cacheTime) {
            try {
                DefaultDingTalkClient client = new DefaultDingTalkClient(URLConstant.URL_GET_TOKKEN);
                OapiGettokenRequest request = new OapiGettokenRequest();

                request.setAppkey(Constant.APPKEY);
                request.setAppsecret(Constant.APPSECRET);
                request.setHttpMethod("GET");
                OapiGettokenResponse response = client.execute(request);
                bizLogger.info("access token get");
                if (response.getErrcode().intValue() == 0) {
                    // 保存accessToken
                    JSONObject jsonAccess = new JSONObject();
                    accToken = response.getAccessToken();
                    jsontemp.clear();
                    jsontemp.put("access_token", accToken);
                    jsontemp.put("begin_time", curTime);
                    jsonAccess.put(secret, jsontemp);
                    FileUtils.write2File(jsonAccess, "accesstoken");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            return accessTokenValue.getString("access_token");
        }
        return accToken;
    }

    /**
     ** 在此方法中，为了避免频繁获取jsapiticket， 在距离上一次获取jsapiticket时间在两个小时之内的情况， 将直接从持久化存储中读取jsapiticket
     */
    public static String getJsApiTicket() {
        String secret = Constant.APPKEY + Constant.APPSECRET;
        long curTime = System.currentTimeMillis();
        JSONObject jsapiticketValue = (JSONObject) FileUtils.getValue("jsapiticket", secret);
        String ticket = "";
        JSONObject jsontemp = new JSONObject();
        if (jsapiticketValue == null || curTime - jsapiticketValue.getLong("begin_time") >= cacheTime) {
            try {
                DefaultDingTalkClient client = new DefaultDingTalkClient(URLConstant.URL_GET_JSAPI_TICKET);
                OapiGetJsapiTicketRequest req = new OapiGetJsapiTicketRequest();
                req.setTopHttpMethod("GET");
                OapiGetJsapiTicketResponse response = client.execute(req, getAccessToken());

                if (response.getErrcode().intValue() == 0) {
                    // 保存jsApiTicket
                    JSONObject jsonAccess = new JSONObject();
                    ticket = response.getTicket();
                    jsontemp.clear();
                    jsontemp.put("ticket", ticket);
                    jsontemp.put("begin_time", curTime);
                    jsonAccess.put(secret, jsontemp);
                    FileUtils.write2File(jsonAccess, "jsapiticket");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            return jsapiticketValue.getString("ticket");
        }
        return ticket;
    }

    public static String sign(String ticket, String nonceStr, long timeStamp, String url) throws OApiException {
        try {
            return DingTalkJsApiSingnature.getJsApiSingnature(url, nonceStr, timeStamp, ticket);
        } catch (Exception ex) {
            throw new OApiException(0, ex.getMessage());
        }
    }

    /**
     * 计算当前请求的jsapi的签名数据<br/>
     * <p>
     * 如果签名数据是通过ajax异步请求的话，签名计算中的url必须是给用户展示页面的url
     *
     * @param request
     * @return
     */
    public static Map<String, Object> getConfig(HttpServletRequest request) {
        String url = request.getParameter("url");
        Map<String, Object> configValue = new HashMap<>();
        /**
         * 确认url与配置的应用首页地址一致
         */
        bizLogger.info(url);

        /**
         * 随机字符串
         */
        String nonceStr = "abcdefg";
        long timeStamp = System.currentTimeMillis() / 1000;
        String signedUrl = url;
        String ticket = null;
        String signature = null;

        try {
            ticket = AuthHelper.getJsApiTicket();
            signature = AuthHelper.sign(ticket, nonceStr, timeStamp, signedUrl);
            configValue.put("status", 1);
        } catch (OApiException e) {
            bizLogger.error(e.getMessage());
            configValue.put("status", -1);
        }

        configValue.put("jsticket", ticket);
        configValue.put("signature", signature);
        configValue.put("nonceStr", nonceStr);
        configValue.put("timeStamp", timeStamp);
        configValue.put("corpId", Constant.CORP_ID);
        configValue.put("agentId", Constant.AGENTID);

        return configValue;
    }
}